#pragma once

#include <assert.h>
#include <mutex>
#include <stdlib.h> // atexit

#include <stdint.h>

namespace detail {
// This doesn't detect inherited member functions!
// http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions
template <typename T> struct has_no_destroy {
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(_MSC_VER)
  template <typename C> static char test(decltype(&C::no_destroy));
#else
  template <typename C> static char test(typeof(&C::no_destroy));
#endif
  template <typename C> static int32_t test(...);
  const static bool value = sizeof(test<T>(0)) == 1;
};
} // namespace detail

template <class T> class Singleton {
public:
  static T &instance() {
    static std::once_flag ponce_;
    std::call_once(ponce_, &Singleton::init);
    assert(value_ != NULL);
    return *value_;
  }

private:
  Singleton();
  ~Singleton();

  static void init() {
    value_ = new T();
    if (!detail::has_no_destroy<T>::value) {
      ::atexit(destroy);
    }
  }

  static void destroy() {
    typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];
    T_must_be_complete_type dummy;
    (void)dummy;

    delete value_;
    value_ = NULL;
  }

private:
  Singleton(const Singleton &) = delete;
  Singleton &operator=(const Singleton &) = delete;

private:
  static std::once_flag ponce_;
  static T *value_;
};

template <typename T> std::once_flag Singleton<T>::ponce_;

template <typename T> T *Singleton<T>::value_ = NULL;
